#include "DirHelper.h"

#include <QDir>
#include <QSet>
#include <QFileInfo>

#ifdef _WIN32
#include "Windows.h"
#endif
/*
 * 参数：@path:根路径 @isLink:是否统计快捷方式
 * 返回<字节总数、文件总数、目录总数>
*/
QStringList calc_ByteCount_FileCount_DirCount(const QString &path,bool isLink)
{
    QList<QString> paths;
    long long sum = 0;
    long long dirs = 0;
    long long files = 0;
    QSet<QString> links;/* 防止循环引用导致的统计错误 */
    paths << path;
    while (paths.size() > 0) {
        QDir dir(paths.first());
        if (isLink) {
            dir.setFilter(QDir::NoDotAndDotDot | QDir::Hidden | QDir::AllDirs | QDir::Files);
        } else {
            dir.setFilter(QDir::NoDotAndDotDot | QDir::Hidden | QDir::AllDirs | QDir::Files | QDir::NoSymLinks);
        }
        QFileInfoList list = dir.entryInfoList();
        for (int i = 0;i < list.size(); ++i) {
            QFileInfo fileInfo = list.at(i);
            if (fileInfo.isDir()) {
                if (isLink) {
                    if (fileInfo.suffix() == "lnk") {
                        if (links.contains(fileInfo.canonicalFilePath())) {
                            continue;
                        } else {
                            links.insert(fileInfo.canonicalFilePath());
                            ++dirs;
                            paths << fileInfo.absoluteFilePath();
                        }
                    } else {
                        paths << fileInfo.absoluteFilePath();
                        ++dirs;
                    }
                } else {
                    paths << fileInfo.absoluteFilePath();
                    ++dirs;
                }
            } else {
                sum += fileInfo.size();
                ++files;
            }
        }
        paths.removeFirst();
    }
    QStringList list;
    list << QString::number(sum) << QString::number(files) << QString::number(dirs);
    return list;
}

bool createHideDir(const QString &path)
{
    QDir dir(path);
    bool flag = false;
    if (!dir.exists())
        flag = dir.mkdir(path);
#ifdef Q_OS_WIN
    flag = SetFileAttributes((LPCWSTR)path.unicode(),FILE_ATTRIBUTE_HIDDEN);
#endif
    return flag;
}

bool createDirLink(const QString &path,QString dstFullPath)
{
#ifdef Q_OS_WIN32
    if (!dstFullPath.endsWith(".lnk"))
        dstFullPath += ".lnk";
#endif
    return QFile::link(path,dstFullPath);
}

/*
 * 注：查找包含文件夹的快捷方式，返回真实路径
 * TODO 优化，这个可以使用多线程来进行优化，如果文件特别多，查找非常耗时
*/
QStringList findFile(const QString &path,const QString &fileName)
{
    QStringList ret;
    QList<QString> paths;
    paths << path;
    QSet<QString> links;/* 防止循环引用导致的统计错误 */

    while (paths.size() > 0) {
        QDir dir(paths.first());
        dir.setFilter(QDir::NoDotAndDotDot | QDir::Hidden | QDir::AllDirs | QDir::Files);

        QFileInfoList list = dir.entryInfoList();
        for (int i = 0;i < list.size(); ++i) {
            QFileInfo fileInfo = list.at(i);
            if (fileInfo.isDir()) {
                if (fileInfo.suffix() == "lnk") {
                    if (links.contains(fileInfo.canonicalFilePath())) {
                        continue;
                    } else {
                        links.insert(fileInfo.canonicalFilePath());
                        paths << fileInfo.absoluteFilePath();
                    }
                } else {
                    paths << fileInfo.absoluteFilePath();
                }
            } else {
                if (fileInfo.fileName() == fileName) {
                    ret << fileInfo.canonicalFilePath();
                }
            }
        }
        paths.removeFirst();
    }
    return ret;
}

QString getAbsoluteFileName(const QString &path,const QString fileName){
    QString myPath = createDirWithName(path);
    if(myPath.isEmpty())
        return "";
#ifdef Q_OS_WIN32
    return myPath + "\\" +fileName;
#else
    return myPath + "/" + fileName;
#endif
}

QString createDirWithName(const QString &dir_name){
    //QDir默认构造为当前路径，当创建是以当前路径为开始创建的
    //macos的运行方式和windows是有区别的。
#ifdef Q_OS_WIN32
    QDir dir = QDir::currentPath() + "\\" +dir_name;
    QStringList list = dir.absolutePath().split("\\");
    QString mid = "\\";
#else
    QDir dir = QDir::currentPath() + "/" +dir_name;
    QStringList list = dir.absolutePath().split("/");
    QString mid = "/";
#endif
    if(dir.exists()){
        return dir.absolutePath();
    }
    QString path;
    for(QStringList::const_iterator it = list.begin(); it != list.end(); ++it){
        path += *it;
        path += mid;
        if(!dir.exists(path))
            if(!dir.mkdir(path)){
                return "";
            }
    }
    return dir.absolutePath();
}
